home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_400
/
425_01
/
tar
/
extract.c
< prev
next >
Wrap
Text File
|
1994-04-02
|
14KB
|
485 lines
/* extarct.c - extract files from (tape) archive.
* This is a part of the Tar program (see file tar.c)
* Author: T.V.Shaporev
* Creation date: 14 Dec 1990
*/
#include <stdio.h>
#include "sysup.h"
#include "nodedef.h"
#include "modern.h"
#ifdef MODERN
# include <string.h>
#else
char *strncpy();
int strlen();
#endif
#ifndef MSDOS
int mknod(), chown(), utime();
long time();
#endif
#include "zippipe.h"
#include "lzwbits.h"
#include "lzwhead.h"
#include "compress.h"
#include "define.h"
#include "lzpack.h"
static int soctus __ARGS__(( register char *, register short* ));
int soctul __ARGS__(( register char *, register long * ));
static int mismatch __ARGS__(( register char *, register char *, int ));
#define octal(c) (((c)&0370)=='0')
static char unknown[] = "Tar: \'%s\' unknown file type \'%c\'\n";
#define _unknown (unknown+9)
static int soctus(s, u)
register short *u;
register char *s;
{
register i;
while (*s == ' ') ++s;
for (*u=0, i=0; octal(*s) && i<7; i++, s++) *u = (*u<<3)|(*s&7);
return *s!=' ' && *s!='\0';
}
int soctul(s, u)
register long *u;
register char *s;
{
register i;
while (*s == ' ') ++s;
for (*u=0, i=0; octal(*s) && i<11; i++, s++) *u = (*u<<3)|(*s&7);
return *s!=' ' && *s!='\0';
}
int gethead()
{
short n;
static short errcount = 0;
register char *err_text = "Tar: bad directory structure\n";
if ((hblock = readtape()) == NULL) return ERROR;
if ((hblock->name[0]) == '\0') {
return errcount ? (++errcount, ERROR) : FALSE;
}
if (soctus(hblock->chksum, &n)) goto bad;
if (n != headsum(hblock)) {
err_text = "Tar: directory checksum error\n"; goto bad;
}
if (soctus(hblock->mode, (short*)&(st.st_mode)) ||
soctus(hblock->uid, (short*)&(st.st_uid)) ||
soctus(hblock->gid, (short*)&(st.st_gid)) ||
soctul(hblock->size, (long *)&(st.st_size)) ||
soctul(hblock->mtime, (long *)&(st.st_mtime))) goto bad;
if (hblock->filetype == TF_CHR || hblock->filetype == TF_BLK) {
if (soctus(hblock->x.new.devmajor, &dmajor) ||
soctus(hblock->x.new.devminor, &dminor)) goto bad;
}
if (errcount != 0) {
(void)fprintf(myout,
"Tar: %d blocks skipped to find header\n", errcount);
errcount = 0;
}
if (hblock->filetype == TF_OLD || hblock->filetype == TF_REG) {
(void)soctul(hblock->x.old.srclen, &codesize); /* no sence for */
(void)soctul(hblock->x.old.srcsum, &longcsum); /* non-packed file */
} else {
longcsum = codesize = 0;
}
return TRUE;
bad:
if (errcount++ == 0) (void)fprintf(myout, err_text);
if (!i_flag) done(ERREAD);
return ERROR;
}
static int tstfield __ARGS__(( char *, int ));
static int tstfield(s,n) /* is the field a valid octal number? */
char *s; int n;
{
register j;
for (j=0; j<n && octal(s[j]); j++);
if (!j || j >= n) return FALSE;
if (s[j] == ' ') ++j;
while (j<n && !s[j++]);
return j>=n;
}
#define TstField(x) tstfield(x, sizeof(x))
short isextent(allx, allb)
short *allx; long *allb;
{
short n;
if ((hblock->filetype != TF_OLD && hblock->filetype != TF_REG) ||
!TstField(hblock->x.s_v.extent) ||
!TstField(hblock->x.s_v.allext) ||
!TstField(hblock->x.s_v.total)) return ERROR;
(void)soctus(hblock->x.s_v.extent, &n);
(void)soctus(hblock->x.s_v.allext, allx);
(void)soctul(hblock->x.s_v.total, allb);
return n < 1 || n > *allx || *allb <= st.st_size ? ERROR : n;
}
int ismagic()
{
register i;
register char *p, *q;
static char magic_list[][8] = { TMAGIC, GMAGIC };
if (hblock->filetype != TF_OLD) {
for (i=0; i<dimof(magic_list); i++) {
p = magic_list[i];
q = hblock->x.new.magic;
while (*q && *q == *p) {
++q; p++;
}
if (*q == '\0' && (*p == '\0' || *p == ' '))
return magic_list[i][0];
}
}
return 0;
}
char prefix()
{
switch (hblock->filetype) {
case TF_CTG: /* ??? contiguous file */
case TF_OLD:
case TF_REG:
case TF_LNK: return ' ';
case TF_SYM: return 'l';
case TF_CHR: return 'c';
case TF_BLK: return 'b';
case TF_DIR: return 'd';
case TF_QUE: return 'p';
case GF_DMP: return 'D';
case GF_MUL: return ',';
case GF_VOL: return 'v';
}
return '?';
}
int usize() /* is it valid to use file size in header */
{
switch (hblock->filetype) {
case TF_OLD: case TF_REG: case TF_CTG:
case GF_DMP: case GF_MUL: case GF_SPR: /* what's it? I wonder */
return TRUE;
}
return FALSE;
}
void skipfile()
{
register long blocks;
for (blocks=(st.st_size+BLKSIZE-1)/BLKSIZE; blocks>0; blocks--) {
if (readtape() == NULL) {
(void)fprintf(myout, "Tar: tape read error\n");
if (i_flag) done(ERREAD);
return;
}
}
}
static int mismatch(p, s, l)
register char *p, *s; int l;
{
register i;
for (i=0; *p && i<l; ++p, i++) {
if (*p == '*') {
while (*++p == '*') ;
while (l>=i) {
if (!mismatch(p, s+i, l-i)) return FALSE;
++i;
}
return TRUE;
} else if (*p != '?') {
if (s[i] != *p) return ERROR;
}
}
return *p || i<l;
}
int inargs(argc, argv, n)
int argc; register char *argv[], *n;
{
register i; register j; register k;
register char *p;
for (i=0; i<argc; i++) {
if (s_flag) {
for (p=argv[i], j=0; j<MAXTNAME && p[j]==n[j] && p[j]!=0; j++);
if (j<MAXTNAME && p[j]==0 && (n[j]==0 || n[j]=='/')) return TRUE;
} else {
j = 0;
while (j<MAXTNAME && n[j]) {
do ++j; while (n[j]!='/' && n[j]!=0);
k = mismatch(argv[i], n, j);
if (k == ERROR) goto extloop;
if (k == FALSE) return TRUE;
}
}
extloop:;
}
return FALSE;
}
void scantape(argc, argv, handler)
int argc; char *argv[]; void (*handler)__ARGS__((void));
{
register k;
while ((k=gethead()) != FALSE) {
if (k == ERROR) continue;
if (argc < 1 || inargs(argc, argv, hblock->name)) {
(*handler)();
} else {
if (usize()) skipfile();
}
}
if (pktype == PKZIP) {
while ((k=unzread((char*)hblock, BLKSIZE)) == BLKSIZE);
if (k != ERROR) {
if (k) (void)fprintf(myout, "Tar: final block misaligned\n");
k = unzclose();
}
if (k) {
register char *p = NULL;
if (k == -1) p = "error"; else if (v_flag) p = "warning";
if (p) (void)fprintf(myout, "Tar: unzip %s: %s\n",
p, ziperrlist[ziperror]);
}
}
}
extern long thisread;
extern int arcget __ARGS__(( void ));
void catalog()
{
register long thislen;
register reverse = FALSE, skipped = FALSE;
register char *p;
static no_mem = FALSE;
short nx = 1, allx; long xinfo;
extern char ofname[];
register c;
p = hblock->name;
c = hblock->filetype;
if (v_flag) prmode(prefix(), (int)(st.st_mode));
if ((c == TF_OLD || c == TF_REG) && (nx=isextent(&allx, &xinfo)) < 1) {
if (st.st_size <= codesize) {
reverse = TRUE;
} else if (pktype == PKfLZW) {
register i, j;
i = strlen(hblock->name);
if (hblock->name[--i] == 'Z' && hblock->name[--i] == '.') {
p = strncpy(ofname, hblock->name, MAXTNAME);
(void)z_getmem(BITS);
codesize = 0; thisread = 0;
if ((j = dbegin(arcget)) == 0) {
do {
if ((j = dpiece(pk_out, pksize)) > 0) codesize += j;
} while (j == pksize);
skipped = TRUE;
} else if (j > 0) {
bacouple(); /* file is not in compressed format */
} else if (!no_mem) {
(void)fprintf(myout, "